/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package estate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
/**
 *
 * @author Wlodek
 */



class EstateRadixSort {
    public static void EstateRadixSort(ArrayList<Estate> l){
        List[] kolejkaZliczanych ;
        int ilosc_kubkow=0;

        //po rozkladowe
        ilosc_kubkow=2;
        kolejkaZliczanych = new LinkedList[ilosc_kubkow];
        for(int i=0;i<ilosc_kubkow;i++)
            kolejkaZliczanych[i] = new LinkedList();

        for(int i=0;i<l.size();i++){
            if(((Dekorator)l.get(i)).getTypOferty()==2 && ((DekoratorLokalowy)l.get(i)).getCzyRozkladowy()==true){
                kolejkaZliczanych[0].add(l.get(i));
            }
            else{
                kolejkaZliczanych[1].add(l.get(i));
            }
        }
        l.clear();
        l.addAll(kolejkaZliczanych[0]);
        l.addAll(kolejkaZliczanych[1]);


        //sortowanie po pietrze
        ilosc_kubkow=200;
        kolejkaZliczanych = new LinkedList[ilosc_kubkow];
        for(int i=0;i<ilosc_kubkow;i++)
            kolejkaZliczanych[i] = new LinkedList();

        for(int i=0;i<l.size();i++){
            if(((Dekorator)l.get(i)).getTypOferty()==2 && ((DekoratorLokalowy)l.get(i)).getPietro()>=0 && ((DekoratorLokalowy)l.get(i)).getPietro()<200)
                kolejkaZliczanych[((DekoratorLokalowy)l.get(i)).getPietro()%ilosc_kubkow].add(l.get(i));
            else if(((DekoratorLokalowy)l.get(i)).getPietro()>=200)kolejkaZliczanych[ilosc_kubkow-1].add(l.get(i));
            else kolejkaZliczanych[0].add(l.get(i)); //dla uproszczenia przyjmujemy, ze mieszkanie na -1 pietrze jest tyle samo warte co mieszkanie ma parterze
        }
        l.clear();
        for(int i=0;i<ilosc_kubkow;i++){
            l.addAll(kolejkaZliczanych[i]);
        }


        //sortowanie po roku budowy
        ilosc_kubkow=400;
        kolejkaZliczanych = new LinkedList[ilosc_kubkow];
        for(int i=0;i<ilosc_kubkow;i++)
            kolejkaZliczanych[i] = new LinkedList();

        for(int i=0;i<l.size();i++){
            if(((Dekorator)l.get(i)).getTypOferty()==2 &&  ((DekoratorBudynkowy)((DekoratorLokalowy)l.get(i)).element).getRokBudowy()-1900>=0)
                kolejkaZliczanych[ilosc_kubkow-1-(((DekoratorBudynkowy)((DekoratorLokalowy)l.get(i)).element).getRokBudowy()-1900)%ilosc_kubkow].add(l.get(i)); //algorytm dziala poprawnie do roku 2300
            else kolejkaZliczanych[0].add(l.get(i)); //przyjmujemy, ze budynki zbudowane przed 1900 rokiem to zabytki
        }
        l.clear();
        for(int i=0;i<ilosc_kubkow;i++){
            l.addAll(kolejkaZliczanych[i]);
        }


        //sortowanie po liczbie pokoi/lazienek
        ilosc_kubkow=60;
        kolejkaZliczanych = new LinkedList[ilosc_kubkow];
        for(int i=0;i<ilosc_kubkow;i++)
            kolejkaZliczanych[i] = new LinkedList();

        for(int i=0;i<l.size();i++){
            if(((Dekorator)l.get(i)).getTypOferty()==2 && ((DekoratorLokalowy)l.get(i)).getLiczbaLazieniek()>=0 && ((DekoratorLokalowy)l.get(i)).getLiczbaLazieniek()<60)
                kolejkaZliczanych[ilosc_kubkow-1-((DekoratorLokalowy)l.get(i)).getLiczbaLazieniek()%ilosc_kubkow].add(l.get(i));
            else if(((Dekorator)l.get(i)).getTypOferty()==2 && ((DekoratorLokalowy)l.get(i)).getLiczbaLazieniek()>=60)kolejkaZliczanych[0].add(l.get(i));
            else kolejkaZliczanych[ilosc_kubkow-1].add(l.get(i));// nie zwracamy wyjatku w razie bledu, poniewaz komplikowaloby to w znaczny sposob nasza aplikacje
        }
        l.clear();
        for(int i=0;i<ilosc_kubkow;i++){
            l.addAll(kolejkaZliczanych[i]);
        }


        //sortowanie po metrazu
        ilosc_kubkow=50;
        kolejkaZliczanych = new LinkedList[ilosc_kubkow];
        for(int i=0;i<ilosc_kubkow;i++)
            kolejkaZliczanych[i] = new LinkedList();

        for(int i=0;i<l.size();i++){
            if(((Dekorator)l.get(i)).getTypOferty()==2 && ((DekoratorLokalowy)l.get(i)).getPowierzchnia()>=0 &&  ((DekoratorLokalowy)l.get(i)).getPowierzchnia()<1000)
                kolejkaZliczanych[ilosc_kubkow-(( ((DekoratorLokalowy)l.get(i)).getPowierzchnia()/20)%ilosc_kubkow)-1].add(l.get(i));
            else if(((Dekorator)l.get(i)).getTypOferty()==2 &&  ((DekoratorLokalowy)l.get(i)).getPowierzchnia()>=1000)kolejkaZliczanych[0].add(l.get(i));
            else kolejkaZliczanych[ilosc_kubkow-1].add(l.get(i));// ujemny metraz moglby byc nadużywany w pozycjonowaniu ofert, dlatego wpisujemy go na koniec
        }
        l.clear();
        for(int i=0;i<ilosc_kubkow;i++){
            l.addAll(kolejkaZliczanych[i]);
        }


        //sortowanie po cenie
        ilosc_kubkow=500;
        kolejkaZliczanych = new LinkedList[ilosc_kubkow];
        for(int i=0;i<ilosc_kubkow;i++)
            kolejkaZliczanych[i] = new LinkedList();

        for(int i=0;i<l.size();i++){
            if(((Dekorator)l.get(i)).getTypOferty()==2 &&  ((Oferta)((DekoratorLokalowy)l.get(i)).element).getCena()>=0 && ((Oferta)((DekoratorLokalowy)l.get(i)).element).getCena()<500000)
                kolejkaZliczanych[(((Oferta)((DekoratorLokalowy)l.get(i)).element).getCena()/1000)%ilosc_kubkow].add(l.get(i));// algorytm zaklada ze statystycznie bardzo rzadko ceny miekszan sa wieksze niz 500 tys, wtedy bowiem dziala niepoprawnie dla cen
            else kolejkaZliczanych[ilosc_kubkow-1].add(l.get(i));// za wysoka lub ujemna cena moglaby byc nadużywana w pozycjonowaniu ofert, dlatego wpisujemy ja na koniec
        }
        l.clear();
        for(int i=0;i<ilosc_kubkow;i++){
            l.addAll(kolejkaZliczanych[i]);
        }

    }
}

class PorownanieKaskadoweOfert implements Comparator<Estate> {

    public int compare(Estate arg0, Estate arg1) {

        if(((Dekorator)arg0).getTypOferty()==2){

            //kolejne sortowanie
            if(((Oferta)((DekoratorLokalowy)arg0).element).getCena()!=((Oferta)((DekoratorLokalowy)arg1).element).getCena()){ //sortowanie po większej cenie
                return ((Oferta)((DekoratorLokalowy)arg0).element).getCena()-((Oferta)((DekoratorLokalowy)arg1).element).getCena();
            }
            else if (((DekoratorLokalowy)arg0).getPowierzchnia()!=((DekoratorLokalowy)arg1).getPowierzchnia()){ //sortowanie po większym metrażu
                    return ((DekoratorLokalowy)arg1).getPowierzchnia()-((DekoratorLokalowy)arg0).getPowierzchnia();
            }
            else if (((DekoratorLokalowy)arg0).getLiczbaLazieniek()!=((DekoratorLokalowy)arg1).getLiczbaLazieniek()){ //sortowanie po liczbie pokoi
                    return ((DekoratorLokalowy)arg1).getLiczbaLazieniek()-((DekoratorLokalowy)arg0).getLiczbaLazieniek();
            }
            else if (((DekoratorBudynkowy)((DekoratorLokalowy)arg0).element).getRokBudowy()!=((DekoratorBudynkowy)((DekoratorLokalowy)arg1).element).getRokBudowy()){ //po roku budowy
                    return ((DekoratorBudynkowy)((DekoratorLokalowy)arg1).element).getRokBudowy()-((DekoratorBudynkowy)((DekoratorLokalowy)arg0).element).getRokBudowy();
            }
            else if (((DekoratorLokalowy)arg0).getPietro()!=((DekoratorLokalowy)arg1).getPietro()){ //im mniejsze piętro, tym lepsza Estate
                    return ((DekoratorLokalowy)arg0).getPietro()-((DekoratorLokalowy)arg1).getPietro();
            }
            else if (((DekoratorLokalowy)arg0).getCzyRozkladowy()!=((DekoratorLokalowy)arg1).getCzyRozkladowy()){ //jeżeli pierwsze mieszkanie jest rozkładowe, to znaczy że jest lepsze
                if(((DekoratorLokalowy)arg0).getCzyRozkladowy() == true)
                    return 1;
                else return 0;
            }
            else return 0;
            
        }else return 0;
    }
}


public class Fasada1 {
    private ArrayList<Estate> katalogOfert;





    private ArrayList<Estate> wyszukaj_m_z_n(int m)
    {
        ArrayList<Estate> al = new ArrayList<Estate>();
        al.addAll(this.katalogOfert);

        //nasza metoda inteligentnie rozstrzyga czy warto uzywac sortowania pozycyjnego, czy korzystniej uzyc sortowania szybkiego
        
        if(al.size()>185)
            EstateRadixSort.EstateRadixSort(al);
        else Collections.sort((List)al);

        int rozmiar=al.size();
        if(rozmiar>3){
            for(int i=3;i<rozmiar;i++){
                al.remove(al.get(3));
            }
        }
        return al;
    }
    public ArrayList<Estate> wyszukaj(Estate wzorzec){return null;}

    public String zestawOferty(HashMap<String,Object> wz)
    {
        FabrykaAbstrakcyjna f = new FabrykaStandard();
        Estate wzorzec = f.stworzOferte(wz);

        if(katalogOfert == null)katalogOfert = wyszukaj(wzorzec);
        String s = wyszukaj_m_z_n(wz.size()/15).toString();

        return s;

    }

    public boolean stworzUsera(HashMap<String,Object> user){
        UsersFactory uf = new UsersFactory();
        uf.createUser(user);
        return true;
    }
}
